package game;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;

import javax.swing.*;

import sun.audio.AudioPlayer;
import sun.audio.AudioStream;

public class Listener extends MouseAdapter implements ActionListener
{
	public static String action; 
	private String name;
	private static int x;
	private static int y;
	static int hardMines= 99;
	static int medMines= 40;
	static int easyMines= 10;
	static int hardx= 30;
	static int hardy= 16;
	static int medx= 16;
	static int medy= 16;
	static int easyx= 10;
	static int easyy= 10;
	private static int numMines;
	private static Grid gboard;
	private static JButton[][] board;
	private static Frame changeFrame;
	private static Frame gframe;
	private static JButton easy;
	private static JButton hard;
	private static JButton med;
	private static int counter;
	private static boolean win= true;
	private static int playAgain;
	private static Set<Coordinate> nc = new HashSet<Coordinate>();
	private static Set<Coordinate> fc= new HashSet<Coordinate>();
	private static JLabel mines= new JLabel();
	public static int minesLeft;
	
	public Listener(String name)
	{
		this.name= name;
	}
	
	public String getName()
	{
		return name;
	}
	
	public void actionPerformed(ActionEvent e) 
	{
		action= e.getActionCommand();
		if (action== "Instructions")
		{
			JOptionPane.showMessageDialog(null, "Instructions: The purpose of the game is to open all the cells of the board which do not contain a bomb. \nYou lose if you set off a bomb cell. Every non-bomb cell you open will tell you the total number of bombs in the eight neighboring cells. \nOnce you are sure that a cell contains a bomb, you can right-click to put a flag it on it as a reminder. \nOnce you have flagged all the bombs around an open cell, you can quickly open the remaining non-bomb cells by clicking on the cell.");
		}
		if (action== "Change Level")
		{
			JPanel jp= new JPanel();
			easy= new JButton("Easy");
			med= new JButton("Medium");
			hard= new JButton("Hard");
			easy.addActionListener(new Listener("easy"));
			med.addActionListener(new Listener("med"));
			hard.addActionListener(new Listener("hard"));
			jp.add(easy); jp.add(med); jp.add(hard);
			changeFrame= new Frame(jp, 300, 100);
			changeFrame.setLocation(0, 150);
			changeFrame.setVisible(true);
		}
		else if (action== "Hard")
		{
			x= hardx;
			y= hardy;
			numMines= hardMines; 
			this.newGame();
			changeFrame.removeNotify();
		}
		else if (action== "Medium")
		{
			x= medx;
			y= medy;
			numMines= medMines;
			this.newGame();
			changeFrame.removeNotify();
		}
		else if (action== "Easy")
		{
			x= easyx;
			y= easyy;
			numMines= easyMines;
			this.newGame();
			changeFrame.removeNotify();
		}
		else if (action== "Exit")
			System.exit(1);
		else if (action== "Play")
			this.newGame();
		else if (action== "m")
		{
			for (int i=0; i<x; i++)
			{
				for (int j=0; j<y; j++)
				{
					if (board[i][j].getActionCommand()== "m")
					{
						board[i][j].setIcon(new ImageIcon(
								(new ImageIcon("images/mineImage.gif")).getImage().getScaledInstance(
								20, 20, java.awt.Image.SCALE_SMOOTH)));
					}
				}
			}
			try {
				playAudio();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			
			playAgain= JOptionPane.showConfirmDialog(null, "Oops, you hit a mine! Sorry, but you have lost this game. \nWould you like to play again?", "You Lost!", JOptionPane.YES_NO_OPTION);
			if (playAgain== JOptionPane.YES_OPTION)
				this.newGame();
			else
				System.exit(1);
			win= false;
		}
		else
		{
			for (int i=0; i< x; i++)
			{
				for (int j=0; j< y; j++)
				{
					if ((action== board[i][j].getActionCommand()) && (board[i][j].getIcon()== null))
					{
						int n = gboard.getNumSurMines(new Coordinate(i,j));
						nc.clear();
						showCell(i, j, n, nc);
					}
				}
			}
			isVictory();	
		}
	}
	public void mouseClicked(MouseEvent e)
	{
		if (e.getButton()== MouseEvent.BUTTON3)
		{
			for (int i=0; i<x; i++)
			{
				for (int j=0; j<y; j++)
				{
					Component button= (Component) board[i][j];
					if (e.getComponent().equals(button))
					{
						if (board[i][j].isEnabled())
						{
							if (board[i][j].getIcon()== null)
							{
								board[i][j].setIcon(new ImageIcon(
										(new ImageIcon("images/flag.jpg")).getImage().getScaledInstance(
										20, 20, java.awt.Image.SCALE_SMOOTH)));
								board[i][j].setActionCommand(Integer.toString(i)+ Integer.toString(j));
								fc.add(new Coordinate(i,j));
								minesLeft--;
								mines.setText(Integer.toString(minesLeft));
							}
							else
							{
								board[i][j].setIcon(null);
								if (gboard.isMine(new Coordinate(i,j)))
									board[i][j].setActionCommand("m");
								fc.remove(new Coordinate(i,j));
								minesLeft++;
								mines.setText(Integer.toString(minesLeft));
							}
						}
					}	
				}
			}
		}			
	}
	public boolean isVictory()
	{
		if (counter== (x*y-numMines) && !(win))
		{
			playAgain= JOptionPane.showConfirmDialog(null, "Congratulations, you have won!\nWould you like to play again?", "You won!", JOptionPane.YES_NO_OPTION);
			if (playAgain== JOptionPane.YES_OPTION)
				this.newGame();
			else
				System.exit(1);		
		}
			return (counter== (x*y-numMines));
	}
	public void newGame()
	{
		if (gframe!= null)
			gframe.removeNotify();
		if ((x!= 0) && (y!= 0) && (numMines!= 0))
			gboard= new Grid(x, y, numMines);
		else
		{
			x= easyx; y= easyy; numMines= easyMines;
			gboard= new Grid(x, y, numMines);
		}
		JPanel game= new JPanel(new GridLayout(y+1, x));
		board= new JButton[x][y];
		for (int i=0; i<x; i++)
		{
			for (int j=0; j<y; j++)
			{
				if (gboard.isMine(new Coordinate(i,j)))
				{
					board[i][j]= new JButton();
					board[i][j].setActionCommand("m");
				}
				else
				{
					board[i][j]= new JButton();
					String ix= Integer.toString(i);
					String iy= Integer.toString(j);
					board[i][j].setActionCommand(ix+iy);
				}
				board[i][j].addActionListener(new Listener("coordinate"));
				board[i][j].addMouseListener(new Listener("mcoordinate"));
				game.add(board[i][j]);
			}
		}
		minesLeft= numMines;
		mines.setFont(new Font("text", Font.BOLD, 12));
		mines.setText(Integer.toString(minesLeft)+ " Mines Left");
		game.add(mines);
		gframe= new Frame(game,x*25,y*25);	
		gframe.setLocation(300,150);	
		gframe.setIconImage(new ImageIcon("images/mineImage.gif").getImage());
		gframe.setVisible(true);
	}
	public String getAction()
	{
		return action;
	}

	public void showCell(int i, int j, int n, Set<Coordinate> set) {
		Coordinate c = new Coordinate(i, j);
		if (n== 0) {
			
			if (!(set.contains(c))) {
				set.add(c);
				board[i][j].setEnabled(false);
				counter++;
			}
			Set<Coordinate> sc= gboard.getAllNeighbors(c);
			if (sc!= null) {
				for (Coordinate cc: sc) {
					if (!(fc.contains(cc)))
					{
						if (!(set.contains(cc)))
							showCell(cc.getX(), cc.getY(), gboard.getNumSurMines(cc), set);
					}
				}
			}
		} else {
			if (board[i][j].isEnabled()) {
				counter++;
				board[i][j].setEnabled(false);
			}
			board[i][j].setFont(new Font("num", Font.BOLD, 12));
			board[i][j].setText(Integer.toString(gboard.getNumSurMines(new Coordinate(i,j))));
			board[i][j].setHorizontalTextPosition((SwingConstants.LEADING));

		}
	}
	void playAudio() throws IOException {
		  InputStream in = new FileInputStream("sounds/Blast.wav");
		  AudioStream as = new AudioStream(in);
		  AudioPlayer.player.start(as);  
	}
}
